#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "analyse_chaine.h"
#include "expressions.h"
#include "instructions.h"

/*
	Rôle
	----
	fonction qui teste si un mot fait partie de la liste des instructions
	Renvoi -1 si le mot n en fait pas partie
	
*/

int isinst(char* mot){
	char *debut = NULL, *suiv = NULL;
	char* inst[]={"REM","GOTO","LET","PRINT","INPUT","IF"};
	int i = 0 , nb_inst = 6;
	debut = lire_mot(mot,&suiv);
	for(  i = 0; i < nb_inst; i += 1 )
		if(strcmp(inst[i],debut)==0)
			return i;
	return -1 ;
	
}

/*
	Rôle
	----
	fonction qui construit les structures d instructions ligne par ligne
	
	
*/



Une_inst *construire_inst(Un_prog *pprog,char *ligne){
	
	char *mot=NULL, *mot_suiv=NULL;
	Un_label *plab;
	Une_inst *pinst;
	pinst = creer_inst();
	// lecture du premier mot
	//
	mot = lire_mot(ligne, &mot_suiv);
	if (*mot == '_')
	{
		if ((plab = rechercher_label(pprog, mot)))
		plab->pinst = pinst;
		else
		pprog->plabel = ajouter_label(pprog, mot, pinst);
		mot = lire_mot(mot_suiv, &mot_suiv);
	}
	//identification du mot cle
	//
	switch (isinst(mot))
	{
	case REM : 	pinst->type = REM;
				construire_inst_rem(pprog, pinst, mot_suiv);
				break;
	case GOTO : pinst->type = GOTO;
				construire_inst_goto(pprog, pinst, mot_suiv);
				break;
	case LET : pinst->type = LET;
				construire_inst_let(pprog, pinst, mot_suiv);
				break;
	case PRINT : pinst->type = PRINT;
				construire_inst_print(pprog, pinst, mot_suiv);
				break;
	case INPUT : pinst->type = INPUT;
				construire_inst_input(pprog, pinst, mot_suiv);
				break;
	case IF : pinst->type = IF;
				construire_inst_if(pprog, pinst, mot_suiv);
				break;
	default : fprintf(stderr, "Mot cle inconnu : %s !!!", mot)
				;
	exit(1);
				}
	return  pinst;
}

/*
	Rôle
	----
	fonction qui  cree une instruction de type REM => commentaire 
	
*/


void construire_inst_rem(Un_prog *pprog, Une_inst *pinst, char *str){
	char *suiv = NULL;
	pinst->rem_str = lire_mot(str,&suiv) ;
	
}

/*
	Rôle
	----
	fonction qui  cree une instruction de type IF
	
*/


void construire_inst_if(Un_prog *pprog, Une_inst *pinst, char *str){
	char *mot = xmalloc(strlen(str)) ;
	char *suiv =NULL , *suiv1 = NULL;
	Un_label *lab= (Un_label*)xmalloc(sizeof(Un_label));
	//construction de l expression
	pinst->pexpr = const_expr(pprog,str,&suiv);
	mot = lire_mot(suiv,&suiv1);
	// teste de la presente du THEN 
	if(strcmp(mot,"THEN")!=0){
		fprintf(stderr,"Erreur instruction IF !!! %s ",mot);
		exit(1);
	}
	mot =  lire_mot(suiv1,&suiv);
	
	// verification du label 
	if(*mot!='_')
	{
		fprintf(stderr,"Erreur !!! %s ",mot);
		exit(1);	
	}
	
	//recherche et ajout du label 
	lab = rechercher_label(pprog,mot);
	if(lab==NULL){
		
		pprog->plabel = ajouter_label(pprog, mot, NULL);
		lab = rechercher_label(pprog,mot);
	}
	pinst->branch_lab = lab ;
	
}

/*
	Rôle
	----
	fonction qui  cree une instruction de type GOTO
	
*/

void construire_inst_goto(Un_prog *pprog, Une_inst *pinst, char *str){
	char *mot = xmalloc(strlen(str)) ;
	char *suiv =NULL;
	Un_label *lab= (Un_label*)xmalloc(sizeof(Un_label));
	mot = lire_mot(str,&suiv);
	//verificatoin du label 
	if(*mot!='_')
	{
		fprintf(stderr,"Erreur !!! %s ",mot);
		exit(1);	
	}
	
	//recherche du label
	lab = rechercher_label(pprog,mot);
	if(lab==NULL){
		//fprintf(stderr,"Erreur !!! Label %s indefini",mot);
		//exit(1);	
		
	
		pprog->plabel = ajouter_label(pprog, mot, NULL);
		lab = rechercher_label(pprog,mot); 
	}
	pinst->branch_lab = lab ;
	
}
/*
	Rôle
	----
	fonction qui  cree une instruction de type PRINT 
	
*/


void construire_inst_print(Un_prog *pprog, Une_inst *pinst, char *str){
	char* suiv = NULL;
	//affectation de l expression 
	pinst->pexpr = const_expr(pprog,str,&suiv);
}

/*
	Rôle
	----
	fonction qui  cree une instruction de type INPUT
	
*/


void construire_inst_input(Un_prog *pprog, Une_inst *pinst, char *str){
	char* var = xmalloc(strlen(str)) ,*suiv = NULL;
	Une_var *pvar = (Une_var*) xmalloc(sizeof(Une_var)) ;
	var = lire_mot(str,&suiv);
	//verification de la variable 
	if(!isalpha(*var)|| (strlen(var)<1)){
		fprintf(stderr,"Erreur !!! %s ",var);
		exit(1);
	}
	//recherche de la variable 
	pvar = rechercher_var(pprog, var);
	if (!pvar){
		pprog->pvar = ajouter_var(pprog, var);
		pvar = rechercher_var(pprog, var);
	}
	pinst->pvar = pvar ;
	
}
/*
	Rôle
	----
	fonction qui  cree une instruction de type LET 
	
*/

void construire_inst_let(Un_prog *pprog, Une_inst *pinst, char *str){
	char* var = xmalloc(strlen(str)) ,*suiv = NULL,*suiv1=NULL;
	Une_var *pvar = (Une_var*) xmalloc(sizeof(Une_var)) ;
	var = lire_mot(str,&suiv);
	//verification de la variable destination 
	if(!isalpha(*var)|| (strlen(var)<1)){
		printf("Erreur !!! ");
		exit(1);
	}
	//recherche de la variable
	pvar = rechercher_var(pprog, var);
	if (!pvar){
		pprog->pvar = ajouter_var(pprog, var);
		pvar = rechercher_var(pprog, var);
	}
	pinst->pvar = pvar ;
	//construction de l expression 
	pinst->pexpr = const_expr(pprog,suiv,&suiv1);	
}

/*
	Rôle
	----
	Fonction qui ajoute l instruction cree a la structure pprog
	
*/

Un_prog *ajouter_inst(Un_prog *pprog,Une_inst *pinst){
	Une_inst *inst = pprog->pinst;
	if(pprog->pinst==NULL)
		pprog->pinst = pinst ;
	else{
		while(inst->suiv!=NULL)
			inst = inst->suiv;
		inst->suiv = pinst ;
	}
	return  pprog ;
	
}


